package com.example.mq.service.impl;

import com.example.mq.dto.MsgConsumeRetryResult;
import com.example.mq.po.MsgConsumePO;
import com.example.mq.retry.DelayLevelEnums;
import com.example.mq.service.MsgConsumeRetry;
import org.apache.commons.lang3.Range;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;

/*
@description:
@ClassName DefaultMsgConsumeRetry
@author chen
@create 2025-08-22 17:28
@Version 1.0
*/
@Component
public class DefaultMsgConsumeRetry implements MsgConsumeRetry
{

    private static Map<Range<Integer>, DelayLevelEnums> retryDelayLevelMap = new LinkedHashMap<>();

    //默认重试次数
    private static final Integer MAX_RETRY_COUNT = 50;


    static
    {
        retryDelayLevelMap.put(Range.between(0, 5), DelayLevelEnums.SECOND_10);
        retryDelayLevelMap.put(Range.between(6, 10), DelayLevelEnums.SECOND_30);
        retryDelayLevelMap.put(Range.between(11, 15), DelayLevelEnums.MINUTE_1);
        retryDelayLevelMap.put(Range.between(16, 20), DelayLevelEnums.MINUTE_5);
        retryDelayLevelMap.put(Range.between(21, 50), DelayLevelEnums.MINUTE_10);
    }

    @Override
    public MsgConsumeRetryResult getRetryResult(MsgConsumePO msgConsumePO)
    {
        MsgConsumeRetryResult mqSendRetryResult = new MsgConsumeRetryResult();
        //当前失败次数 < 最大重试次数，则可以继续重试
        if (msgConsumePO.getFailCount() < MAX_RETRY_COUNT)
        {
            //获取延迟时间
            long delayTimeInMills = this.getDelayTimeInMills(msgConsumePO.getFailCount());
            //下次重试时间（当前时间+延迟时间）
            LocalDateTime nextRetryTime = LocalDateTime.now().plus(Duration.ofMillis(delayTimeInMills));
            mqSendRetryResult.setNextRetryTime(nextRetryTime);
            mqSendRetryResult.setRetry(true);
        }
        else
        {
            mqSendRetryResult.setRetry(false);
        }
        return mqSendRetryResult;
    }


    private long getDelayTimeInMills(int failCount)
    {
        for (Map.Entry<Range<Integer>, DelayLevelEnums> entry : retryDelayLevelMap.entrySet())
        {
            Range<Integer> range = entry.getKey();
            if (range.contains(failCount))
            {
                return entry.getValue().getDelayTimeInMills();
            }
        }
        return DelayLevelEnums.HOUR_1.getDelayTimeInMills();
    }
}
